package cn.wolfcode.service.impl;

import cn.wolfcode.domain.Permission;
import cn.wolfcode.mapper.PermissionMapper;
import cn.wolfcode.qo.QueryObject;
import cn.wolfcode.service.IPermissionService;
import cn.wolfcode.util.RequirePermission;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;


import java.util.Collection;
import java.util.List;
import java.util.Map;

@Service
public class PermissionServiceImpl implements IPermissionService {
    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    @Transactional
    public void saveOrUpdate(Permission permission) {
        if(permission.getId() != null){
            permissionMapper.updateByPrimaryKey(permission);
        }else {
            permissionMapper.insert(permission);
        }
    }

    @Override
    @Transactional
    public void delete(Long id) {
        permissionMapper.deleteByPrimaryKey(id);
    }

    @Override
    public Permission selectOne(Long id) {
        Permission permission = permissionMapper.selectByPrimaryKey(id);
        return permission;
    }

    @Override
    public List<Permission> selectAll() {
        List<Permission> permissions = permissionMapper.selectAll();
        return permissions;
    }

    @Override
    public List<String> queryExpByEid(Long id) {
        List<String> list = permissionMapper.queryExpByEid(id);
        return list;
    }

    @Override
    public PageInfo<Permission> queryPage(QueryObject qo) {
        PageHelper.startPage(qo.getCurrentPage(),qo.getPageSize());
        List<Permission> permissions = permissionMapper.queryPage(qo);
        return new PageInfo<>(permissions);
    }


    //使用RequestMappingHandLerMapping的方式
    //这个爆红是假错
    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Override
    public void reload() {
        //从数据库获取所有的权限表达式集合
        List<String> exp = permissionMapper.selectByExp();

        //handlerMapping可以直接获取控制层的方法
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();

        //获取方法对象的集合
        Collection<HandlerMethod> methods = handlerMethods.values();

        //遍历每个方法,判断有没有权限注解
        for (HandlerMethod method : methods) {
            //获取单个方法的权限注解
            RequirePermission methodAnnotation = method.getMethodAnnotation(RequirePermission.class);
            //判断是否为空,空则跳过
            if(methodAnnotation == null){
                continue;
            }

            //不为空就获取里面的值
            String name = methodAnnotation.name();
            String expression = methodAnnotation.expression();

            //判断表达式是否已经再数据库存在,直接跳过
            if(exp.contains(expression)){
                continue;
            }

            //如果不存在则保存到数据库
            Permission permission = new Permission();
            permission.setName(name);
            permission.setExpression(expression);
            permissionMapper.insert(permission);

            //然后也保存到判断用的表达式集合中
            exp.add(expression);
        }
    }

    //扫描所有权限数据,并保存到数据库中

    /*@Autowired
    private ApplicationContext ctx;

    @Override
    public void reload() {
        //先再数据库查询所有的权限表达式的集合
        List<String> exp = permissionMapper.selectByExp();

        //从容器中获取所有控制器的bean对象,根据类上的注解为控制器获取
        //此时会把数据存在map中,map的value值即对应的控制器bean对象
        Map<String, Object> map = ctx.getBeansWithAnnotation(Controller.class);

        //获取所有控制器bean对象
        Collection<Object> controllers = map.values();

        //遍历这个控制器对象集合,然后从每个对象再获取里面的方法对象
        for(Object controller : controllers){
            //此时的controller时bean对象,需要转换为字节码对象,反射获取里面的方法对象
            Class<?> aClass = controller.getClass();
            //获取这个字节码对象里的所有方法,使用getDeclaredMethods是为了不获取父类的方法
            Method[] methods = aClass.getDeclaredMethods();
            //遍历所有方法判断是否有贴权限注解
            for(Method method : methods){
                //获取这个方法的权限注解对象
                RequirePermission annotation = method.getAnnotation(RequirePermission.class);

                //根据判断这个权限注解对象是否为null来判断是否有贴权限注解
                if(annotation == null){
                    //没贴直接跳过
                    continue;
                }

                //没跳过说明贴了,获取里面的表达式和名称
                String expression = annotation.expression();
                String name = annotation.name();

                // 先判断数据库是否已经存在这个表达式
                if(exp.contains(expression)){
                    continue;
                }

                //如果不存在,则把这个权限数据封装到权限对象中,并插入到数据库中
                Permission permission = new Permission();
                permission.setExpression(expression);
                permission.setName(name);
                permissionMapper.insert(permission);

                //把插入的新权限数据也保存到前面的表达式集合中
                exp.add(expression);
            }
        }
    }*/
}
